/*********************************************************************
* 
* S3PICPROG -  PIC programmer
* Copyright (C) 2008 Olivier Ringot <oringot@gmail.com>
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, 
* Boston, MA  02110-1301, USA.
* 
**********************************************************************
* 
* $Revision: $
* $Date: $
* $Source: $
* $Log: $
*
*********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include "icsp.h"

int main(int argc,char **argv)
{
  FILE     *file_in;
  unsigned int i,j,k,address,data,blank,hit_error;
  unsigned char config_buffer[16];
  unsigned char line_buffer[256];
 
  unsigned char c;
  char          *s;
  
  icsp_ttys=open("/dev/ttyS0",O_RDWR);
  if(icsp_ttys==-1)
  {
    printf("error: unable to open /dev/ttyS0\n");
    exit(-1);
  }
  
  if(argc!=2)
  {
    printf("error: bad argument number !\n");
    printf("usage: %s <file.hex>\n",argv[0]);
    exit(-1);
  }

  file_in = fopen(argv[1],"rb");
  if(!file_in)
  {
    printf("error: unable to open file %s \n",argv[1]);
    exit(-1);
  }

  for(i=0;i<16;i++)
  {
    config_buffer[i]=0xff;  
  }
  
  fgets(line_buffer,256,file_in);
  s=strtok(line_buffer," ");
  address=strtoul(s,(char**)NULL,16);
  if(address!=0x300000)
  {
    printf("error: hex file shall start with address at 0x300000 !\n");
    exit(-1);
  }

  for(i=0;i<16;i++)
  {
    s=strtok(NULL," ");
    if(!s) break;
    data=strtoul(s,(char**)NULL,16);
    config_buffer[i]=data;
  }
  
  /* init delay */
  icsp_delays(4,4,4);
  
  /* enter ICSP */
  icsp_enter();
  
  /* CONFIG programming */
  printf("config bits programming...\r");
  for(i=0;i<16;i++)
  {
    icsp_write_tblptr(0x300000+i);
    icsp_write_prog((config_buffer[i]&0xff)|((config_buffer[i]&0xff)<<8));
    icsp_delays(0x0004,0x186a,0x0271);
    icsp_core_instr(0x0000);
    icsp_delays(0x0004,0x0004,0x0004);
  }
  printf("config bits programming done\n");
  
  /* CONFIG verifying */
  printf("CONFIG verifying...\r");
  hit_error=0;
  for(i=0;i<16;i++)
  {
    if(i==4 || i==7 || i==0xe || i==0xf)
    {
    }
    else
    {
      icsp_write_tblptr(0x300000+i);
      data=icsp_read();
      if(data!=config_buffer[i])
      {
        printf("mismatch at 0x%-.6x, read 0x%-.2x, expected 0x%-.2x\n",
               0x300000+i,data,config_buffer[i]);
        hit_error++;
      }
    }
  }
  
  if(hit_error)
  {
    printf("config bits programmed with %d error(s) !\n",hit_error);
  }
  else
  {
    printf("config bits programmed and verified.\n");
  }
  
  /* leave ICSP */
  icsp_exit();
  
  fclose(file_in);
  close(icsp_ttys);
}
